home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 151-175 / scopedisk168 / tinytools / clip / clip.asm < prev    next >
Assembly Source File  |  1995-03-19  |  8KB  |  337 lines

  1. ; Clip input lines on specified locations and write result to standard output.
  2.  
  3.        INCLUDE "/include/init.i"
  4.  
  5. ;      OPT     D+
  6.  
  7. ; Local Equs
  8.  
  9. MaxLineSize    EQU     512
  10.  
  11. ; Variable storage
  12.  
  13.        STRUCT  ArgArray,(4+1)*4
  14.        LONG    StdIn
  15.        LONG    StdOut
  16.        LONG    ByteFetch
  17.        LONG    ReadBytesLeft
  18.        LONG    Count1
  19.        LONG    Count2
  20.        LONG    Delta1
  21.        LONG    Delta2
  22.        LONG    ID1StrPtr
  23.        LONG    ID2StrPtr
  24.        LONG    ID1Exclusive
  25.        LONG    ID2Exclusive
  26.        SIZE
  27.  
  28. ; Regs
  29.  
  30.  
  31. Delta          EQUR    D4
  32. Count          EQUR    D5
  33. LineBufPtr     EQUR    D6
  34. LineBufLeft    EQUR    D7
  35. LineEndPtr     EQUR    A2
  36. IDStrPtr       EQUR    A3
  37. ErrorStrPtr    EQUR    A4
  38.  
  39. ; Startup
  40.  
  41.        STACK   4000
  42.        INIT
  43.  
  44. ; Let ARP interpret the commandline
  45.  
  46.        MOVE.L  ComLineBase(GP),A0
  47.        MOVE.L  ComLineSize(GP),D0
  48.        LEA     HelpMsg(PC),A1
  49.        LEA     ArgArray(GP),A2
  50.        LEA     Template(PC),A3
  51.        MOVE.L  A1,(A2)
  52.        CALL    GADS
  53.        MOVE.L  (A2),ErrorStrPtr
  54.        TST.L   D0
  55.        BEQ     ErrorExit
  56.        BMI     ErrorExit
  57.  
  58. ; Interpret the count values
  59.  
  60.        MOVE.L  ArgArray+0*4(GP),A0
  61.        BSR     GetSignedNum
  62.        BEQ     ErrorExit
  63.        MOVE.L  D0,Count1(GP)
  64.        MOVE.L  D1,Delta1(GP)
  65.  
  66.        MOVE.L  ArgArray+2*4(GP),A0
  67.        BSR     GetSignedNum
  68.        BEQ     ErrorExit
  69.        MOVE.L  D0,Count2(GP)
  70.        MOVE.L  D1,Delta2(GP)
  71.  
  72. ; Interpret the ID strings
  73.  
  74.        LEA     EmptyString(PC),A1
  75.  
  76.        MOVE.L  ArgArray+1*4(GP),D0
  77.        BNE.S   ID1StringSpecified
  78.        MOVE.L  A1,D0
  79. ID1StringSpecified:
  80.        MOVE.L  D0,A0
  81.  
  82.        CMP.B   #'x',(A0)
  83.        BNE.S   NoID1Exclusion
  84.        ADDQ.L  #1,A0
  85.        ADDQ.L  #1,ID1Exclusive(GP)
  86. NoID1Exclusion:
  87.        MOVE.L  A0,ID1StrPtr(GP)
  88.  
  89.        MOVE.L  ArgArray+3*4(GP),D0
  90.        BNE.S   ID2StringSpecified
  91.        MOVE.L  A1,D0
  92. ID2StringSpecified:
  93.        MOVE.L  D0,A0
  94.  
  95.        CMP.B   #'x',(A0)
  96.        BNE.S   NoID2Exclusion
  97.        ADDQ.L  #1,A0
  98.        ADDQ.L  #1,ID2Exclusive(GP)
  99. NoID2Exclusion:
  100.        MOVE.L  A0,ID2StrPtr(GP)
  101.  
  102. ; Open the standard input & output
  103.  
  104.        CALL    Input
  105.        MOVE.L  D0,StdIn(GP)
  106.        CALL    Output
  107.        MOVE.L  D0,StdOut(GP)
  108.  
  109. ; Allocate the read-line buffer
  110.  
  111.        LEA     OutOfMem(PC),ErrorStrPtr
  112.        MOVE.L  #MaxLineSize+4+MaxLineSize,D0   ; 2 part buf with 0 term space.
  113.        MOVEQ   #0,D1
  114.        CALL    ArpAllocMem
  115.        MOVE.L  D0,LineBufPtr
  116.        BEQ     ErrorExit
  117.  
  118.  
  119. ; ** This is an intelligent ReadLine routine.
  120.  
  121. ; Reinitialize the line buffer. (First part of dual buffer space)
  122.  
  123. DoForEachLine:
  124.        LEA     ReadError(PC),ErrorStrPtr
  125.        MOVE.L  LineBufPtr,LineEndPtr
  126.        MOVE.L  #MaxLineSize,LineBufLeft
  127.  
  128. ; Extract lines from the readbuffer into the line buffer.
  129.  
  130.        BRA.S   ExtractEntry
  131. CopyLineBytes:
  132.        MOVE.L  ByteFetch(GP),A0
  133.        ADDQ.L  #1,ByteFetch(GP)
  134.        SUBQ.L  #1,ReadBytesLeft(GP)
  135.        MOVE.B  (A0),D0
  136.        CMP.B   #10,D0
  137.        BEQ.S   GotLine
  138.        MOVE.B  D0,(LineEndPtr)+
  139.        SUBQ.L  #1,LineBufLeft
  140.        BEQ.S   GotLine
  141. ExtractEntry:
  142.        TST.L   ReadBytesLeft(GP)               ; Stack vars 0 init
  143.        BNE     CopyLineBytes
  144.  
  145. ; Refill the read buffer.
  146.  
  147.        MOVE.L  StdIn(GP),D1
  148.        MOVE.L  LineBufPtr,D2
  149.        MOVE.L  #MaxLineSize,D3
  150.        ADD.L   D3,D2
  151.        ADDQ.L  #4,D2
  152.        CALL    Read
  153.        TST.L   D0
  154.        BMI     ErrorExit
  155.        BNE.S   NotYetDone
  156.        CMP.L   LineBufPtr,LineEndPtr
  157.        BEQ.S   Exit
  158. NotYetDone:
  159.        MOVE.L  D2,ByteFetch(GP)
  160.        MOVE.L  D0,ReadBytesLeft(GP)
  161.        BNE     CopyLineBytes
  162.  
  163. ; Adjust end of line pointer and weed out empty lines
  164.  
  165. GotLine:
  166.        SUBQ.L  #1,LineEndPtr
  167.        CMP.L   LineBufPtr,LineEndPtr
  168.        BLO     DoForEachLine
  169.  
  170. ; Find the initial clip postition
  171.  
  172.        MOVE.L  LineBufPtr,A0
  173.        MOVE.L  Delta1(GP),Delta
  174.        BPL.S   InitialPosSet
  175.        MOVE.L  LineEndPtr,A0
  176. InitialPosSet:
  177.        MOVE.L  Count1(GP),Count
  178.        MOVE.L  ID1StrPtr(GP),IDStrPtr  
  179.        BSR.S   FindClipPosition
  180.        BNE     DoForEachLine
  181.        MOVE.L  A0,D3
  182.  
  183. ; Find the secondary clip postition.
  184.  
  185.        MOVE.L  Delta2(GP),Delta
  186.        MOVE.L  Count2(GP),Count
  187.        MOVE.L  ID2StrPtr(GP),IDStrPtr
  188.        BSR.S   FindClipPosition
  189.        BNE     DoForEachLine
  190.  
  191. ; Adjust for direction, adjust for exclusion and compute the length.
  192.  
  193.        MOVE.L  ID1Exclusive(GP),D0
  194.        MOVE.L  ID2Exclusive(GP),D1
  195.        CMP.L   A0,D3
  196.        BHI.S   InvertedDirection
  197.        EXG     D0,D1
  198.        EXG     A0,D3
  199. InvertedDirection:
  200.        ADD.L   D1,A0
  201.        SUB.L   D0,D3
  202.        SUB.L   A0,D3
  203.        BMI     DoForEachLine
  204.        ADDQ.L  #2,D3
  205.  
  206. ; Terminate with a LF and write the line clip.
  207.  
  208.        LEA     WriteError(PC),ErrorStrPtr
  209.        MOVE.B  #10,-1(A0,D3.L)
  210.        MOVE.L  StdOut(GP),D1
  211.        MOVE.L  A0,D2
  212.        CALL    Write
  213.        CMP.L   D0,D3
  214.        BNE.S   ErrorExit
  215. WriteDone:
  216.  
  217. ; Check if user hit ^C 
  218.  
  219. SkipWrite:
  220.        SUB.L   A1,A1
  221.        CALL    CheckAbort
  222.        MOVE.L  A1,ErrorStrPtr
  223.        TST.L   D0
  224.        BNE.S   ErrorExit
  225.        BRA     DoForEachLine
  226.  
  227. ; Done, cleanup
  228.  
  229. Exit:
  230.        CLR.W   ReturnCode(GP)
  231.        SUB.L   ErrorStrPtr,ErrorStrPtr
  232. ErrorExit:
  233.  
  234. ; Display error string, if any, and exit
  235.  
  236.        MOVE.L  ErrorStrPtr,D0
  237.        BEQ.S   NoErrorMsg
  238.        MOVE.L  D0,A1
  239.        CALL    Puts
  240. NoErrorMsg:
  241.        RTS
  242.  
  243. ; Subroutines
  244.  
  245. ; This subroutine tried to find the CNTth position in the current line (relative
  246. ; to the initial position) which matches the ID string.
  247. ; I : A0 = Initial search position
  248. ; O : A0 = Clip position
  249. ;   : Z=1 if search succeeded.
  250. ;   : LineBufPtr,LineEndPtr,Delta,Count,IDStrPtr should be initialized
  251.  
  252. FindClipPosition:
  253.  
  254. ; Set the boundary to check with in D0 (Given position movement direction)
  255.  
  256.        MOVE.L  LineBufPtr,D0
  257.        TST.L   Delta
  258.        BMI.S   FetchedRelevantBoundary
  259.        MOVE.L  LineEndPtr,D0
  260. FetchedRelevantBoundary:
  261.  
  262. ; Check if all matches found or boundary reached. If not move current position.
  263.  
  264.        TST.L   Count
  265. CheckNextByte:
  266.        BEQ.S   GotClipPosition
  267. NoByteMatch:
  268.        CMP.L   D0,A0
  269.        BEQ.S   AtLineBoundary
  270.        ADD.L   Delta,A0
  271.  
  272. ; Check byte on the current position matched the ID string.
  273.  
  274.        TST.B   (IDStrPtr)
  275.        BEQ.S   ByteMatched
  276.        MOVE.L  IDStrPtr,A1
  277.        MOVE.B  (A0),D1
  278. TryToMatchNextByte:
  279.        CMP.B   (A1)+,D1
  280.        BEQ.S   ByteMatched
  281.        TST.B   (A1)
  282.        BEQ     NoByteMatch
  283.        BRA     TryToMatchNextByte
  284. ByteMatched:
  285.        SUBQ.L  #1,Count
  286.        BRA     CheckNextByte
  287.  
  288. ; Done. Take care of the Z-flag.
  289.  
  290. AtLineBoundary:
  291.        TST.B   (IDStrPtr)
  292. GotClipPosition:
  293.        RTS
  294.  
  295. ; This sub decodes an ASCII buffer containing a signed number to a positive
  296. ; number and a sign boolean. It also sets ErrorStrPtr to "Invalid count"
  297. ; I : A0 = Ptr ASCII buffer
  298. ; O : D0.L = Integer >= 0
  299. ;   : D1.L = +1 if positive, -1 if negative
  300. ;   : Z = 1 if error
  301.  
  302. GetSignedNum:
  303.        LEA     InvalidCnt(PC),ErrorStrPtr
  304.        MOVEQ   #-1,D1
  305.        CMP.B   #'-',(A0)+
  306.        BEQ.S   ConvertToLong
  307.        MOVEQ   #+1,D1
  308.        CMP.B   #'+',-(A0)
  309.        BNE.S   ConvertToLong
  310.        ADDQ.L  #1,A0
  311. ConvertToLong:
  312.        MOVE.L  D1,-(SP)
  313.        CALL    Atol
  314.        MOVEM.L (SP)+,D1
  315.        RTS
  316.  
  317. ; The string section
  318.  
  319. Template:
  320.        DC.B    'CNT1/a,ID1/k,CNT2/a,ID2/k',0
  321. HelpMsg:
  322.        DC.B    'Clip - Pipe through clipped lines.',10
  323.        DC.B    'Usage: Clip <Cnt1> [ID1 [x]"charlist"] <RelCnt2> [ID2 [x]"charlist"]',0
  324. OutOfMem:
  325.        DC.B    'Out of memory!',0
  326. InvalidCnt:
  327.        DC.B    'Invalid count',0
  328. ReadError:
  329.        DC.B    'Error while reading',0
  330. WriteError:
  331.        DC.B    'Error while writing',0
  332. EmptyString:
  333.        DC.B    0
  334.        CNOP    0,2
  335.  
  336.        END
  337.